home *** CD-ROM | disk | FTP | other *** search
- /*
- * glmethods.c
- *
- * Support routines for SGI/RS6000 machines.
- *
- * Copyright (C) 1989, 1991, Craig E. Kolb, Allan Snyder
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- * glmethods.c,v 4.1 1994/08/09 08:07:59 explorer Exp
- *
- * glmethods.c,v
- * Revision 4.1 1994/08/09 08:07:59 explorer
- * Bump version to 4.1
- *
- * Revision 1.1.1.1 1994/08/08 04:52:29 explorer
- * Initial import. This is a prerelease of 4.0.6enh3, or 4.1 possibly.
- *
- * Revision 4.0.1.4 92/01/10 17:17:39 cek
- * patch3: Added heightfield support.
- *
- * Revision 4.0.1.3 91/12/13 11:43:11 cek
- * patch3: Spot direction and spread now set correctly.
- * patch3: Set GLC_OLDPOLYGON to 0 on sgi machines to fix VGX weirdness.
- *
- * Revision 4.0.1.2 91/10/10 22:45:27 cek
- * patch1: Added spotlight support.
- *
- * Revision 4.0.1.1 1991/09/29 15:28:36 cek
- * patch1: Added support for transparency.
- *
- * Revision 4.0 91/07/17 17:38:43 kolb
- * Initial version
- *
- */
- #include <gl.h>
- #include <device.h>
- #include "rayshade.h"
- #include "options.h"
- #include "viewing.h"
-
- #include "libsurf/surface.h"
-
- #include "libobj/box.h"
- #include "libobj/cone.h"
- #include "libobj/csg.h"
- #include "libobj/cylinder.h"
- #include "libobj/disc.h"
- #include "libobj/hf.h"
- #include "libobj/grid.h"
- #include "libobj/instance.h"
- #include "libobj/list.h"
- #include "libobj/plane.h"
- #include "libobj/poly.h"
- #include "libobj/sphere.h"
- #include "libobj/triangle.h"
-
- #include "liblight/light.h"
- #include "liblight/extended.h"
- #include "liblight/infinite.h"
- #include "liblight/point.h"
- #include "liblight/spot.h"
-
- #define CIRCLE_SAMPLES 20 /* # of samples around circle (cone/cyl/etc) */
- #define DEFAULT_NEAR .2 /* default value for near clipping plane */
- #define DEFAULT_FAR 350. /* default far clipping plane */
- #define PLANE_RAD 450. /* radius of disc used to represent planes */
-
- #ifndef SPHERELIB
- #define SPHERE_LEVEL 3
- #endif
-
- /*
- * Pass a normal stored in a Vector to the geometry pipeline.
- */
- #define GLNormal(w) (glnrm[0] = (w)->x, glnrm[1] = (w)->y, \
- glnrm[2] = (w)->z, n3f(glnrm))
-
- static void GLBoxDraw(), GLConeDraw(), GLCsgDraw(), GLCylinderDraw(),
- GLDiscDraw(),
- GLGridDraw(), GLHfDraw(), GLInstanceDraw(),
- GLListDraw(), GLPlaneDraw(), GLPolygonDraw(),
- GLSphereDraw(), GLTorusDraw(), GLTriangleDraw(),
- GLBoundsDraw(),
- GLInfiniteLight(), GLPointLight(), GLSpotLight(),
- GLExtendedLight();
-
- static short cursurf = 1,
- curlight = 1;
-
- static Object GLBoxObject,
- GLCylObject,
- GLSphereObject,
- GLBoxObjectDefine(),
- GLCylObjectDefine();
-
- extern Object GLSphereObjectDefine();
-
- static int Doublebuffered;
-
- static float Ident[4][4] = {1., 0., 0., 0.,
- 0., 1., 0., 0.,
- 0., 0., 1., 0.,
- 0., 0., 0., 1.},
- glnrm[3];
-
- static float **CirclePoints;
-
- static void LightDraw(), GeomDraw(), GLMultMatrix(),
- GLPushSurface(), GLPopSurface(), LightDrawInit(),
- ObjectInit(), GLDrawFrame(), ScreenDrawInit(), DrawInit(),
- GLUnitCircle(), GLDisc(), ComputeClippingPlanes();
-
- Float CurrentTime;
-
- static unsigned long BackPack; /* Packed background color */
- static long Zinit; /* maximum Zbuffer value */
-
- MethodsRegister()
- {
- BoxMethodRegister(GLBoxDraw);
- ConeMethodRegister(GLConeDraw);
- CsgMethodRegister(GLCsgDraw);
- CylinderMethodRegister(GLCylinderDraw);
- DiscMethodRegister(GLDiscDraw);
- GridMethodRegister(GLGridDraw);
- #ifdef sgi
- HfMethodRegister(GLHfDraw);
- #endif
- InstanceMethodRegister(GLInstanceDraw);
- ListMethodRegister(GLListDraw);
- PlaneMethodRegister(GLPlaneDraw);
- PolygonMethodRegister(GLPolygonDraw);
- SphereMethodRegister(GLSphereDraw);
- /*TorusMethodRegister(GLTorusDraw);*/
- TriangleMethodRegister(GLTriangleDraw);
-
- InfiniteMethodRegister(GLInfiniteLight);
- PointMethodRegister(GLPointLight);
- ExtendedMethodRegister(GLExtendedLight);
- SpotMethodRegister(GLSpotLight);
- }
-
- void
- Render()
- {
- short val;
- float tmp;
-
- /*
- * We're only sampling the scene once, so we need
- * not do lots of work to determine exactly what
- * animated transformations are doing...
- */
- Options.samples = 1;
- SamplingSetOptions(Options.samples, Options.gaussian,
- Options.filterwidth);
-
- DrawInit();
- qdevice(ESCKEY);
- qdevice(SPACEKEY);
- qdevice(REDRAW);
-
- DrawFrames();
-
- while (TRUE) {
- switch (qread(&val)) {
- case ESCKEY:
- exit(0);
- break;
- case REDRAW:
- reshapeviewport();
- DrawFrames();
- break;
- case SPACEKEY:
- if (!val)
- DrawFrames();
- break;
- }
- }
- }
-
- DrawFrames()
- {
- int i;
- for (i = 0; i < Options.totalframes; i++)
- GLDrawFrame(i);
- }
-
- static void
- DrawInit()
- {
- extern Surface DefaultSurface;
-
- ScreenDrawInit();
- ObjectInit();
- LightDrawInit();
-
- /*
- * Push the default surface.
- */
- GLPushSurface(&DefaultSurface);
- }
-
- static void
- ScreenDrawInit()
- {
- /*
- * Open window, initialize graphics, etc.
- */
- #ifdef sgi
- foreground();
- #endif
- prefsize(Screen.xsize, Screen.ysize);
- winopen("rayview");
-
- #ifdef sgi
- glcompat(GLC_OLDPOLYGON, 0);
- #endif
-
- RGBmode();
- mmode(MVIEWING);
-
- if (Options.totalframes > 1) {
- Doublebuffered = TRUE;
- doublebuffer();
- }
-
-
- gconfig();
- blendfunction(BF_SA, BF_MSA);
- zbuffer(TRUE);
-
- /*
- * Initialize viewing matrix.
- */
- GLViewingInit();
-
- BackPack = (unsigned char)(255*Screen.background.r) |
- ((unsigned char)(255*Screen.background.g) << 8) |
- ((unsigned char)(255*Screen.background.b) << 16);
- Zinit = getgdesc(GD_ZMAX);
- lsetdepth(0, Zinit);
- }
-
- /*
- * Draw the World object.
- */
- static void
- GLDrawFrame(frame)
- int frame;
- {
- extern Geom *World;
-
- RSStartFrame(frame);
- CurrentTime = Options.framestart;
- TimeSet(CurrentTime);
-
- czclear(BackPack, Zinit);
-
- /*
- * Draw the World object
- */
- GeomDraw(World);
- if (Doublebuffered)
- swapbuffers();
- }
-
- GLViewingInit()
- {
- float near, far, aspect, dist, T[4][4];
- short ang;
- extern Geom *World;
-
- ang = Camera.vfov * 10 + 0.5;
- aspect = Camera.hfov / Camera.vfov;
-
- T[0][0]=Screen.scrni.x; T[0][1]=Screen.scrnj.x; T[0][2]= -Camera.dir.x;
- T[1][0]=Screen.scrni.y; T[1][1]=Screen.scrnj.y; T[1][2]= -Camera.dir.y;
- T[2][0]=Screen.scrni.z; T[2][1]=Screen.scrnj.z; T[2][2]= -Camera.dir.z;
-
- T[0][3] = T[1][3] = T[2][3] = 0.;
-
- T[3][0] = -dotp(&Camera.lookp, &Screen.scrni);
- T[3][1] = -dotp(&Camera.lookp, &Screen.scrnj);
- T[3][2] = dotp(&Camera.lookp, &Camera.dir);
- T[3][3] = 1.;
-
- ComputeClippingPlanes(&near, &far, World->bounds);
-
- loadmatrix(Ident);
- perspective(ang, aspect, near, far);
- polarview((float)Camera.lookdist, 0, 0, 0);
- multmatrix(T);
- }
-
-
- static void
- ObjectInit()
- {
- CircleDefine();
- GLBoxObject = GLBoxObjectDefine();
-
- #ifdef SPHERELIB
- GLSphereObject = GLSphereObjectDefine();
- #else
- GLSphereObject = GLSphereObjectDefine(SPHERE_LEVEL);
- #endif
-
- GLCylObject = GLCylObjectDefine();
- }
-
- static void
- GeomDraw(obj)
- Geom *obj;
- {
- Trans *ct;
- /*
- * If object has a surface associated with it,
- * start using it.
- */
- if (obj->surf)
- GLPushSurface(obj->surf);
- if (obj->trans) {
- /*
- * Take care of any animated transformations that
- * exist.
- */
- if (obj->animtrans && !equal(obj->timenow, CurrentTime)) {
- TransResolveAssoc(obj->trans);
- obj->timenow = CurrentTime;
- }
- pushmatrix();
- /*
- * Apply in reverse order.
- */
- for (ct = obj->transtail; ct; ct = ct->prev)
- GLMultMatrix(&ct->trans);
- }
-
- if (obj->methods->user) {
- /*
- * Call proper method
- */
- (*obj->methods->user)(obj->obj);
- } else {
- /*
- * Draw bounding box.
- */
- GLBoundsDraw(obj->bounds);
- }
-
- if (obj->surf)
- GLPopSurface();
- if (obj->trans)
- popmatrix();
- }
-
- static float surfprops[] = {AMBIENT, 0, 0, 0,
- DIFFUSE, 0, 0, 0,
- SPECULAR, 0, 0, 0,
- SHININESS, 0,
- ALPHA, 1,
- LMNULL};
- static float *amb = &surfprops[1],
- *diff = &surfprops[5],
- *spec = &surfprops[9],
- *shine = &surfprops[13],
- *alpha = &surfprops[15];
-
- static void
- GLPushSurface(surf)
- Surface *surf;
- {
- static Surface *lastsurf = NULL;
-
- /*
- * Start using the given surface.
- * In the case of the use of an "applysurf",
- * the same surface will be applied to many
- * primitives individually. By saving the
- * pointer to the last surface, we keep from
- * lmdef'ing the surface when we don't need to.
- */
- if (surf != lastsurf) {
- amb[0] = surf->amb.r; amb[1] = surf->amb.g;
- amb[2] = surf->amb.b;
- diff[0] = surf->diff.r; diff[1] = surf->diff.g;
- diff[2] = surf->diff.b;
- spec[0] = surf->spec.r; spec[1] = surf->spec.g;
- spec[2] = surf->spec.b;
- shine[0] = surf->srexp;
- *alpha = 1. - surf->transp;
- lmdef(DEFMATERIAL, cursurf, sizeof(surfprops)/sizeof(float),
- surfprops);
- lastsurf = surf;
- }
- lmbind(MATERIAL, cursurf);
- cursurf++;
- }
-
- static void
- GLMultMatrix(trans)
- RSMatrix *trans;
- {
- float newmat[4][4];
- /*
- * Multiply in the given transformation.
- */
- newmat[0][0] = trans->matrix[0][0]; newmat[0][1] = trans->matrix[0][1];
- newmat[0][2] = trans->matrix[0][2]; newmat[0][3] = 0.;
- newmat[1][0] = trans->matrix[1][0]; newmat[1][1] = trans->matrix[1][1];
- newmat[1][2] = trans->matrix[1][2]; newmat[1][3] = 0.;
- newmat[2][0] = trans->matrix[2][0]; newmat[2][1] = trans->matrix[2][1];
- newmat[2][2] = trans->matrix[2][2]; newmat[2][3] = 0.;
- newmat[3][0] = trans->translate.x; newmat[3][1] = trans->translate.y;
- newmat[3][2] = trans->translate.z ; newmat[3][3] = 1.;
- multmatrix(newmat);
- }
-
- static void
- GLPopSurface()
- {
- cursurf--;
- lmbind(MATERIAL, cursurf-1);
- }
-
- static void
- GLBoundsDraw(bounds)
- Float bounds[2][3];
- {
- float sx, sy, sz;
-
- pushmatrix();
-
- translate(bounds[LOW][X], bounds[LOW][Y], bounds[LOW][Z]);
- scale( bounds[HIGH][X] - bounds[LOW][X],
- bounds[HIGH][Y] - bounds[LOW][Y],
- bounds[HIGH][Z] - bounds[LOW][Z]);
- pushmatrix();
- callobj(GLBoxObject);
- popmatrix();
- popmatrix();
- }
-
- static void
- GLBoxDraw(box)
- Box *box;
- {
- GLBoundsDraw(box->bounds);
- }
-
-
- static void
- GLConeDraw(cone)
- Cone *cone;
- {
- int i, j;
- float norm[3], normconst, ZeroVect[3], tmpv[3];
-
- ZeroVect[0] = ZeroVect[1] = ZeroVect[2] = 0.;
- /*
- * Sides.
- * For the normal, assume we are finding the normal at
- * (C_P[i].x, C_P[i].y, 1.) at this point, the unnormalized
- * normal = (C_P[i].x, C_P[i].y, -tantheta^2). When we normalize,
- * then length of the vector is simply equal to:
- * sqrt(CP[i].x^2 + CP[i].y^2 + tantheta^4) ==
- * sqrt(1. + tantheta^4)
- * In our case, tantheta = 1., so...
- */
-
- normconst = 1. / sqrt(2.);
- norm[2] = -normconst;
-
- pushmatrix();
- GLMultMatrix(&cone->trans.trans);
-
- for (i = 0; i < CIRCLE_SAMPLES; i++) {
- j = (i + 1) % CIRCLE_SAMPLES;
- norm[0] = CirclePoints[i][0] * normconst;
- norm[1] = CirclePoints[i][1] * normconst;
- n3f(norm);
- bgnpolygon();
- if (cone->start_dist > EPSILON) {
- tmpv[2] = cone->start_dist;
- tmpv[0] = CirclePoints[i][0] * cone->start_dist;
- tmpv[1] = CirclePoints[i][1] * cone->start_dist;
- v3f(tmpv);
- tmpv[0] = CirclePoints[j][0] * cone->start_dist;
- tmpv[1] = CirclePoints[j][1] * cone->start_dist;
- v3f(tmpv);
- } else
- v3f(ZeroVect);
- tmpv[2] = 1.;
- tmpv[0] = CirclePoints[j][0];
- tmpv[1] = CirclePoints[j][1];
- v3f(tmpv);
- tmpv[0] = CirclePoints[i][0];
- tmpv[1] = CirclePoints[i][1];
- v3f(tmpv);
- endpolygon();
- }
- popmatrix();
- }
-
- static void
- GLCsgDraw(csg)
- Csg *csg;
- {
- /*
- * Punt by drawing both objects.
- */
- GeomDraw(csg->obj1);
- GeomDraw(csg->obj2);
- }
-
- static void
- GLCylinderDraw(cyl)
- Cylinder *cyl;
- {
- pushmatrix();
- GLMultMatrix(&cyl->trans.trans);
- callobj(GLCylObject);
- popmatrix();
- }
-
- static void
- GLDiscDraw(disc)
- Disc *disc;
- {
- GLDisc((Float)sqrt(disc->radius), &disc->pos, &disc->norm);
- }
-
- static void
- GLDisc(rad, pos, norm)
- Float rad;
- Vector *pos, *norm;
- {
- RSMatrix m, tmp;
- Vector atmp;
-
- /*
- * This is kinda disgusting...
- */
- ScaleMatrix(rad, rad, 1., &m);
- if (fabs(norm->z) == 1.) {
- atmp.x = 1.;
- atmp.y = atmp.z = 0.;
- } else {
- atmp.x = norm->y;
- atmp.y = -norm->x;
- atmp.z= 0.;
- }
-
- RotationMatrix(atmp.x, atmp.y, atmp.z, -acos(norm->z), &tmp);
- MatrixMult(&m, &tmp, &m);
- TranslationMatrix(pos->x, pos->y, pos->z, &tmp);
- MatrixMult(&m, &tmp, &m);
- pushmatrix();
- GLMultMatrix(&m);
- /*
- * Draw unit circle.
- */
- GLUnitCircle(0., TRUE);
- popmatrix();
- }
-
- static void
- GLGridDraw(grid)
- Grid *grid;
- {
- Geom *ltmp;
-
- for (ltmp = grid->unbounded; ltmp; ltmp = ltmp->next)
- GeomDraw(ltmp);
- for (ltmp = grid->objects; ltmp; ltmp = ltmp->next)
- GeomDraw(ltmp);
- }
-
- static void
- GLHfDraw(hf)
- Hf *hf;
- {
- int x, y;
- float n[3], v[3], del, del2, del4, dz1, delz, za, zb, zc;
- float bot, top, left, right, len;
-
- del = 1. / (hf->size - 1);
- del2 = del*del;
- del4 = del2*del2;
-
- bot = 0.;
- top = del;
-
- for (y = 0; y < hf->size -1; y++) {
- za = hf->data[y+1][0];
- zb = hf->data[y][0];
- left = 0;
- right = del;
- for (x = 1; x < hf->size; x++) {
- /*
- * A +-+ C
- * |/
- * B +
- */
-
- zc = hf->data[y+1][x];
- dz1 = za - zb;
- delz = za - zc;
- len = sqrt(del2*delz*delz + del2*dz1*dz1 + del4);
- bgnpolygon();
- n[0] = del*delz/len;
- n[1] = -del*dz1/len;
- n[2] = del2/len;
- n3f(n);
- v[0] = left; v[1] = top; v[2] = za; v3f(v);
- v[1] = bot; v[2] = zb; v3f(v);
- v[0] = right; v[1] = top; v[2] = zc; v3f(v);
- endpolygon();
-
- /*
- * B +
- * /|
- * A +-+ C
- */
- za = zb; zb = zc; zc = hf->data[y][x];
- dz1 = zc - za;
- delz = zc - zb;
- len = sqrt(del2*dz1*dz1 + del2*delz*delz + del4);
- n[0] = -del*dz1/len;
- n[1] = del*delz/len;
- n[2] = del2/len;
- bgnpolygon();
- n3f(n);
- v[0] = left; v[1] = bot; v[2] = za; v3f(v);
- v[0] = right; v[2] = zc; v3f(v);
- v[1] = top; v[2] = zb; v3f(v);
- endpolygon();
- left = right;
- right += del;
- za = zb;
- zb = zc;
- }
- bot = top;
- top += del;
- }
-
- }
-
- static void
- GLInstanceDraw(inst)
- Instance *inst;
- {
- GeomDraw(inst->obj);
- }
-
- static void
- GLListDraw(list)
- List *list;
- {
- Geom *ltmp;
-
- for (ltmp = list->unbounded; ltmp; ltmp = ltmp->next)
- GeomDraw(ltmp);
- for (ltmp = list->list; ltmp; ltmp = ltmp->next)
- GeomDraw(ltmp);
- }
-
- static void
- GLPlaneDraw(plane)
- Plane *plane;
- {
- /*
- * Draw a really big disc.
- */
- GLDisc((Float)PLANE_RAD, &plane->pos, &plane->norm);
- }
-
- static void
- GLPolygonDraw(poly)
- register Polygon *poly;
- {
- register int i;
-
- GLNormal(&poly->norm);
-
- bgnpolygon();
- for (i = 0; i < poly->npoints; i++)
- v3d(&poly->points[i]);
- endpolygon();
- }
-
- static void
- GLSphereDraw(sph)
- Sphere *sph;
- {
- pushmatrix();
- translate(sph->x, sph->y, sph->z);
- scale(sph->r, sph->r, sph->r);
- callobj(GLSphereObject);
- popmatrix();
- }
-
- static void
- GLTorusDraw(){}
-
- static void
- GLTriangleDraw(tri)
- register Triangle *tri;
- {
- /*
- * If Float is a double, use v3d,
- * otherwise use v3f.
- */
- if (tri->type != PHONGTRI) {
- GLNormal(&tri->nrm);
- bgnpolygon();
- v3d(&tri->p[0]); v3d(&tri->p[1]); v3d(&tri->p[2]);
- endpolygon();
- } else {
- bgnpolygon();
- GLNormal(&tri->vnorm[0]);
- v3d(&tri->p[0]);
- GLNormal(&tri->vnorm[1]);
- v3d(&tri->p[1]);
- GLNormal(&tri->vnorm[2]);
- v3d(&tri->p[2]);
- endpolygon();
- }
- }
-
- float lightprops[] = {POSITION, 0., 0., 0., 0.,
- LCOLOR, 0, 0, 0,
- SPOTDIRECTION, 0., 0., 0.,
- SPOTLIGHT, 0., 180.,
- LMNULL};
-
- float *lpos = &lightprops[1],
- *lcolor = &lightprops[6],
- *spotdir = &lightprops[10],
- *spotexp = &lightprops[14],
- *spotspread = &lightprops[15];
-
- float lmodel[] = {AMBIENT, 1., 1., 1.,
- ATTENUATION, 1., 0.,
- LOCALVIEWER, 0.,
- #ifdef sgi
- ATTENUATION2, 0.,
- TWOSIDE, 1.,
- #endif
- LMNULL};
-
- static void
- LightDrawInit()
- {
- Light *light;
- extern Light *Lights;
-
- for (light = Lights; light; light = light->next)
- LightDraw(light);
-
- switch (curlight-1) {
- case 8:
- lmbind(LIGHT7, 8);
- case 7:
- lmbind(LIGHT6, 7);
- case 6:
- lmbind(LIGHT5, 6);
- case 5:
- lmbind(LIGHT4, 5);
- case 4:
- lmbind(LIGHT3, 4);
- case 3:
- lmbind(LIGHT2, 3);
- case 2:
- lmbind(LIGHT1, 2);
- case 1:
- lmbind(LIGHT0, 1);
- }
-
- lmodel[1] = Options.ambient.r;
- lmodel[2] = Options.ambient.g;
- lmodel[3] = Options.ambient.b;
-
- lmdef(DEFLMODEL, 1, sizeof(lmodel) / sizeof(float), lmodel);
- lmbind(LMODEL, 1);
- }
-
- static void
- LightDraw(light)
- Light *light;
- {
- if (!light || !light->methods->user)
- return;
- lcolor[0] = light->color.r;
- lcolor[1] = light->color.g;
- lcolor[2] = light->color.b;
- (*light->methods->user)(light->light);
- }
-
- static void
- GLExtendedLight(ext)
- Extended *ext;
- {
- lpos[0] = ext->pos.x;
- lpos[1] = ext->pos.y;
- lpos[2] = ext->pos.z;
- lpos[3] = 1.;
- lmdef(DEFLIGHT, curlight++, sizeof(lightprops)/sizeof(float),
- lightprops);
- }
-
-
- static void
- GLInfiniteLight(inf)
- Infinite *inf;
- {
- lpos[0] = inf->dir.x;
- lpos[1] = inf->dir.y;
- lpos[2] = inf->dir.z;
- lpos[3] = 0.;
- lmdef(DEFLIGHT, curlight++, sizeof(lightprops)/sizeof(float),
- lightprops);
- }
-
- static void
- GLPointLight(pt)
- Pointlight *pt;
- {
- lpos[0] = pt->pos.x;
- lpos[1] = pt->pos.y;
- lpos[2] = pt->pos.z;
- lpos[3] = 1.;
- lmdef(DEFLIGHT, curlight++, sizeof(lightprops) / sizeof(float),
- lightprops);
- }
-
- static void
- GLSpotLight(spot)
- Spotlight *spot;
- {
- lpos[0] = spot->pos.x;
- lpos[1] = spot->pos.y;
- lpos[2] = spot->pos.z;
- lpos[3] = 1.;
- spotdir[0] = spot->dir.x;
- spotdir[1] = spot->dir.y;
- spotdir[2] = spot->dir.z;
- *spotexp = spot->coef;
- *spotspread = 180 * acos(spot->falloff) / PI;
- lmdef(DEFLIGHT, curlight++, sizeof(lightprops) / sizeof(float),
- lightprops);
- /* fix up spot defs so other source methods needn't reset them. */
- *spotspread = 180.;
- *spotexp = 1.;
- }
-
- static float boxfaces[6][4][3] = {
- { {1., 1., 1.},
- {0., 1., 1.},
- {0., 0., 1.},
- {1., 0., 1.} },
- { {1., 0., 1.},
- {0., 0., 1.},
- {0., 0., 0.},
- {1., 0., 0.} },
- { {1., 0., 0.},
- {0., 0., 0.},
- {0., 1., 0.},
- {1., 1., 0.} },
- { {0., 1., 0.},
- {0., 1., 1.},
- {1., 1., 1.},
- {1., 1., 0.} },
- { {1., 1., 1.},
- {1., 0., 1.},
- {1., 0., 0.},
- {1., 1., 0.} },
- { {0., 0., 1.},
- {0., 1., 1.},
- {0., 1., 0.},
- {0., 0., 0.}}};
-
- float boxnorms[6][3] = {
- {0, 0, 1},
- {0, -1, 0},
- {0, 0, -1},
- {0, 1, 0},
- {1, 0, 0,},
- {-1, 0, 0}};
-
- /*
- * Define a unit cube centered at (0.5, 0.5, 0.5)
- */
- static Object
- GLBoxObjectDefine()
- {
- int i, box;
-
- makeobj(box = genobj());
- for (i = 0; i < 6; i++) {
- n3f(boxnorms[i]);
- polf(4, boxfaces[i]);
- }
- closeobj();
- return box;
- }
-
- static void
- GLUnitCircle(z, up)
- float z;
- int up;
- {
- int i;
- float norm[3];
-
- norm[0] = norm[1] = 0.;
- bgnpolygon();
-
- if (up) {
- norm[2] = 1.;
- n3f(norm);
- for (i = 0; i < CIRCLE_SAMPLES; i++) {
- CirclePoints[i][2] = z;
- v3f(CirclePoints[i]);
- }
- } else {
- norm[2] = -1.;
- n3f(norm);
- for (i = CIRCLE_SAMPLES -1; i; i--) {
- CirclePoints[i][2] = z;
- v3f(CirclePoints[i]);
- }
- }
-
- endpolygon();
- }
-
- static Object
- GLCylObjectDefine()
- {
- int i, j, cyl;
- float norm[3];
-
- makeobj(cyl = genobj());
- norm[2] = 0;
- for (i = 0; i < CIRCLE_SAMPLES; i++) {
- j = (i+1)%CIRCLE_SAMPLES;
- norm[0] = CirclePoints[i][0];
- norm[1] = CirclePoints[i][1];
- #ifdef sgi
- n3f(norm);
- bgnpolygon();
- CirclePoints[i][2] = 0;
- v3f(CirclePoints[i]);
- CirclePoints[j][2] = 0;
- v3f(CirclePoints[j]);
- CirclePoints[j][2] = 1;
- v3f(CirclePoints[j]);
- CirclePoints[i][2] = 1;
- v3f(CirclePoints[i]);
- endpolygon();
- #else
- n3f(norm);
- pmv(CirclePoints[i][0], CirclePoints[i][1], 0.);
- pdr(CirclePoints[j][0], CirclePoints[j][1], 0.);
- pdr(CirclePoints[j][0], CirclePoints[j][1], 1.);
- pdr(CirclePoints[i][0], CirclePoints[i][1], 1.);
- pclos();
- #endif
- }
- closeobj();
- return cyl;
- }
-
- /*
- * Fill CirclePoints[t] with X and Y values cooresponding to points
- * along the unit circle. The size of CirclePoints is equal to
- * CIRCLE_SAMPLES.
- */
- CircleDefine()
- {
- int i;
- double theta, dtheta;
-
- dtheta = 2.*M_PI / (double)CIRCLE_SAMPLES;
- CirclePoints = (float **)malloc(CIRCLE_SAMPLES * sizeof(float *));
- for (i = 0, theta = 0; i < CIRCLE_SAMPLES; i++, theta += dtheta) {
- CirclePoints[i] = (float *)malloc(3 * sizeof(float));
- CirclePoints[i][0] = cos(theta);
- CirclePoints[i][1] = sin(theta);
- /* Z is left unset. */
- }
- }
-
- /*
- * Given world bounds, determine near and far
- * clipping planes. Only problem occurs when there are
- * unbbounded objects (planes)...
- */
- static void
- ComputeClippingPlanes(near, far, bounds)
- float *near, *far;
- Float bounds[2][3];
- {
- Vector e, c;
- double rad, d;
-
-
- /*
- * Compute 'radius' of scene.
- */
- rad = max(max((bounds[HIGH][X] - bounds[LOW][X])*0.5,
- (bounds[HIGH][Y] - bounds[LOW][Y])*0.5),
- (bounds[HIGH][Z] - bounds[LOW][Z])*0.5);
-
- c.x = (bounds[LOW][X] + bounds[HIGH][X])*0.5;
- c.y = (bounds[LOW][Y] + bounds[HIGH][Y])*0.5;
- c.z = (bounds[LOW][Z] + bounds[HIGH][Z])*0.5;
-
- /*
- * Compute position of eye relative to the center of the sphere.
- */
- VecSub(Camera.pos, c, &e);
- d = VecNormalize(&e);
- if (d <= rad)
- /*
- * Eye is inside sphere.
- */
- *near = DEFAULT_NEAR;
- else
- *near = (d - rad)*0.2;
- *far = (d + rad)*2.;
- }
-